/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2016 abel533@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.wf.service;

import com.github.pagehelper.PageHelper;
import com.wf.common.util.StringUtil;
import com.wf.dao.MenuMapper;
import com.wf.entity.Menu;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

@Service
public class MenuService {
    @Autowired
    private MenuMapper menuMapper;

    public List<Menu> getAllByPage(Menu menu) {
        if (menu.getPage() != null && menu.getRows() != null) {
            PageHelper.startPage(menu.getPage(), menu.getRows());
        }
        return menuMapper.selectAll();
    }

    public Menu getById(String id) {
        return menuMapper.selectByPrimaryKey(id);
    }

    public void deleteById(String id) {
        menuMapper.deleteByPrimaryKey(id);
    }

    public void save(Menu menu) {
        if (menu.getId() != null) {
            menuMapper.updateByPrimaryKey(menu);
        } else {
            menuMapper.insert(menu);
        }
    }

    public List<Menu> getMenusByUserId(String userId) {
        return menuMapper.getMenusByUserId(userId);
    }

    public List<Menu> getMenusByRoleId(String roleId) {
        return menuMapper.getMenusByRoleId(roleId);
    }


    /**
     * 获取所有菜单
     *
     * @return
     */
    public String getAllMenu() {
        Example example = new Example(Menu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId", "0");
        criteria.andEqualTo("menuType","1");
        example.setOrderByClause("sn desc");
        List<Menu> menus = menuMapper.selectByExample(example);
        JSONArray model = new JSONArray();
        // 获取权限树json
        for (Menu menu : menus) {
            JSONObject mn = new JSONObject();
            mn.put("id", menu.getId());
            mn.put("text", menu.getMenuName());
            getChildrenMenu(menu.getId(), mn);
            model.add(mn);
        }
        return model.toString();
    }

    /**
     * 根据该用户的所有权限菜单
     *
     * @return
     */
    public String getAllMenuByUser(String userId) {
        JSONArray tree = new JSONArray();
        List<Menu> menus = menuMapper.getMenusByUserId(userId);
        for (Menu menu : menus) {
            getParentMenu(menu.getId(), null, tree);
        }
        tree = paixu(tree);
        return tree.toString();
    }

    // 从子到父获取tree
    private void getParentMenu(String id, JSONArray mn, JSONArray tree) {
        JSONArray menua = new JSONArray();
        JSONObject menuo = new JSONObject();
        Menu menu = menuMapper.selectByPrimaryKey(id);
        if (menu != null) {
            menuo.put("id", menu.getId());
            menuo.put("text", menu.getMenuName());
            menuo.put("sn", menu.getSn());
            menuo.put("type", menu.getMenuType());
            menuo.put("state", "close");
            if (!StringUtil.empty(menu.getMenuUrl())) {
                JSONObject attributes = new JSONObject();
                attributes.put("url", menu.getMenuUrl());
                menuo.put("attributes", attributes);
            }
            if (mn != null) {
                menuo.put("children", mn);
            }
            menua.add(menuo);
            boolean is = true;
            if (!StringUtil.empty(menu.getParentId()) && !menu.getParentId().equals("0")) {
                is = pd(menu.getParentId(), menuo, tree);
                if (is) {
                    getParentMenu(menu.getParentId(), menua, tree);
                }
            } else {
                if (is) {
                    tree.add(menuo);
                }

            }
        }
    }
    // 从父到子获取tree
    private void getChildrenMenu(String parentId, JSONObject model) {
        JSONArray menua = new JSONArray();
        Example example = new Example(Menu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId", parentId);
        example.setOrderByClause("sn desc");
        List<Menu> menust = menuMapper.selectByExample(example);
        if (menust!= null &&!menust.isEmpty()) {
            for (Menu menu : menust) {
                JSONObject menuo = new JSONObject();
                menuo.put("id", menu.getId());
                menuo.put("text", menu.getMenuName());
                if (menu.getMenuType().equals("0")) {
                    getChildrenMenu(menu.getId(), menuo);
                }
                menua.add(menuo);
            }
            model.put("children", menua);
        }
    }

    /**
     * 判断父类是否已经添加
     */
    private boolean pd(String parentCode, JSONObject menuo, JSONArray tree) {
        boolean is = true;
        for (Object omenu : tree) {
            JSONObject cmenu = (JSONObject) omenu;
            if (cmenu.get("type").equals("1")) {
                JSONArray cchildren = (JSONArray) cmenu.get("children");
                if (cchildren != null) {
                    if (cmenu.containsValue(parentCode)) {
                        int sn = Integer.parseInt(String.valueOf(menuo.get("sn")));
                        if (cchildren.size() < sn) {
                            sn = cchildren.size() - 1;
                        }
                        cchildren.add(sn, menuo);
                        return false;
                    } else {
                        is = pd(parentCode, menuo, cchildren);
                    }
                }
            }
            if (!is) {
                return is;
            }
        }
        return is;
    }

    /**
     * paixu:tree排序.
     *
     * @param tree
     * @return
     * @author yuzb
     * @since JDK 1.8
     */
    private JSONArray paixu(JSONArray tree) {
        for (int i = 0; i < tree.size(); i++) {
            JSONObject cmenu = (JSONObject) tree.get(i);
            if (cmenu.get("type") != null) {
                JSONArray cchildren = (JSONArray) cmenu.get("children");
                if (cchildren!= null &&!cchildren.isEmpty() && cmenu.get("isarray") == null) {
                    cchildren = paixu(cchildren);
                    cmenu.put("isarray", true);
                }
                for (int j = i + 1; j < tree.size(); j++) {
                    JSONObject cmenui = (JSONObject) tree.get(i);
                    JSONObject cmenuj = (JSONObject) tree.get(j);
                    if (cmenuj.get("type") != null) {
                        JSONArray cchildrenj = (JSONArray) cmenuj.get("children");
                        if (cchildrenj != null &&!cchildrenj.isEmpty() && cmenuj.get("isarray") == null) {
                            cchildrenj = paixu(cchildrenj);
                            cmenuj.put("isarray", true);
                        }
                        int sni = Integer.parseInt(String.valueOf(cmenui.get("sn")));
                        int snj = Integer.parseInt(String.valueOf(cmenuj.get("sn")));
                        if (sni > snj) {
                            JSONObject temp = cmenui;
                            tree.set(i, cmenuj);
                            tree.set(j, temp);
                        }
                    }
                }
            }
        }
        return tree;
    }

}
